package com.controller;

import com.view.AboutDialog;
import com.view.MainFrame;
import com.view.MenuBar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*;

public class InitialThread implements Runnable {

    public static final Logger logger = LoggerFactory.getLogger(InitialThread.class);

    // 主窗口
    public static JFrame main = MainFrame.shared;


    // 菜单栏
    private static JMenuBar mainBar = com.view.MenuBar.mainBar;
    private static JMenu fileMenu = com.view.MenuBar.fileMenu;
    private static JMenuItem scanItem = com.view.MenuBar.scanItem;
    private static JMenuItem saveItem = com.view.MenuBar.saveItem;
    private static JMenuItem exitItem = com.view.MenuBar.exitItem;
    private static JMenuItem aboutItem = com.view.MenuBar.aboutItem;
    private static Map<JMenu, ArrayList<JMenuItem>> menus = MenuBar.menus;

    // 文本标签
    private static JLabel[] labels = new JLabel[4];

    static {
        labels[0] = new JLabel("请选择:");
        labels[1] = new JLabel("端口范围:");
        labels[2] = new JLabel("线程数:");
        labels[3] = new JLabel("扫描结果:");
    }

    // IP扫描和域名扫描的选择按钮
    public static JRadioButton addrScanJRadio1 = new JRadioButton("IP地址:");
    public static JRadioButton domeScanJRadio1 = new JRadioButton("域名:");
    private static ButtonGroup btnGroup1 = new ButtonGroup();
    // TCP和UDP的选择按钮
    public static JRadioButton TCPSelectJRadio2 = new JRadioButton("TCP:");
    public static JRadioButton UDPSelectJRadio2 = new JRadioButton("UDP:");
    public static ButtonGroup btnGroup2 = new ButtonGroup();

    static {

        // 设为默认
        addrScanJRadio1.setSelected(true);
        // 加入按键组
        btnGroup1.add(addrScanJRadio1);
        btnGroup1.add(domeScanJRadio1);
        // 设为默认
        TCPSelectJRadio2.setSelected(true);
        // 加入按键组
        btnGroup2.add(TCPSelectJRadio2);
        btnGroup2.add(UDPSelectJRadio2);
    }

    // 输入IP地址的文本框
    private static JTextField[] ipAddrTextField = new JTextField[5];
    private static JLabel[] symbolLabel = new JLabel[5];

    public static JTextField[] getIpAddrTextField() {
        return ipAddrTextField;
    }

    public static JRadioButton getAddrScanJRadio1() {
        return addrScanJRadio1;
    }

    static {
        for (int i = 0; i < 5; i++) {
            ipAddrTextField[i] = new JTextField("0", 3);
            if (i < 3)
                symbolLabel[i] = new JLabel(".");
            else
                symbolLabel[i] = new JLabel("~");
        }

    }

    // 输入主机名的文本框
    public static JTextField domainNameTextField = new JTextField("localhost", 8);

    static {
        domainNameTextField.setEnabled(false);
    }

    // 输入端口范围的文本框, [0]为起始端口, [1]为结束端口.
    public  static JTextField[] portTextField = new JTextField[2];

    static {
        portTextField[0] = new JTextField("0", 4);
        portTextField[1] = new JTextField("1000", 4);
    }

    // 输入并发线程数量的文本框
    public static JTextField numOfThreadsTextField = new JTextField("100", 3);


    // 按钮
    public static JButton submitBtn = new JButton("开始扫描");
    private static JButton saveBtn = new JButton("保存扫描结果");
    private static JButton exitBtn = new JButton("退出");
    private Container mainJPanel;
    private GridBagConstraints ctrs;
    // 显示扫描结果
    public  static JTextArea resultTextArea = new JTextArea(null, 10, 40);
    // 滚动条面板
    private static JScrollPane resultJPanel =
            new JScrollPane(resultTextArea,
                    JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                    JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    public static JProgressBar progressBar=new JProgressBar();

    /**
     *
     */
    public InitialThread() {

        logger.debug("{}: 主线程类创建", this.getClass().getSimpleName());
        logger.debug("{}: 添加菜单栏和窗体内容", this.getClass().getSimpleName());

        // 添加菜单栏
        for (Map.Entry<JMenu, ArrayList<JMenuItem>> menu : menus.entrySet()) {
            for (JMenuItem item : menu.getValue())
                menu.getKey().add(item);
            mainBar.add(menu.getKey());
        }
        main.setJMenuBar(mainBar);

        // 添加窗体内容
        addWindowBody();


        ActionListenerThread addActionListener = new ActionListenerThread(this);
        addActionListener.start();

    }

    private void addWindowBody() {
        main.setLayout(new GridBagLayout());
        // 初始化面板和布局
        mainJPanel = main.getContentPane();
        ctrs = new GridBagConstraints();
        ctrs.insets = new Insets(11, 0, 0, 10);
        ctrs.fill = GridBagConstraints.BOTH;
        ctrs.anchor = GridBagConstraints.CENTER;
        // 第1行: "请选择"提示
        gridBagAddItem(labels[0],0,0,10);
        //第1行:选择TCP或者UDP
        gridBagAddItem(TCPSelectJRadio2,0,1,1);
        gridBagAddItem(UDPSelectJRadio2,1,1,1);
        // 第3行: IP地址
        gridBagAddItem(addrScanJRadio1, 0, 2, 1);
        for (int i = 0; i < 5; i++) {
            gridBagAddItem(ipAddrTextField[i], 2 * i + 1, 2, 1);
            if (i < 4)
                gridBagAddItem(symbolLabel[i], 2 * i + 2, 2, 1);
        }
        // 第4行: 域名
        gridBagAddItem(domeScanJRadio1, 0, 3, 1);
        gridBagAddItem(domainNameTextField, 1, 3, 3);
        // 第5行: 端口范围
        gridBagAddItem(labels[1], 0, 4, 1);
        gridBagAddItem(portTextField[0], 1, 4, 1);
        gridBagAddItem(symbolLabel[4], 2, 4, 1);
        gridBagAddItem(portTextField[1], 3, 4, 1);
        // 第6行: 线程数
        gridBagAddItem(labels[2], 0, 5, 1);
        gridBagAddItem(numOfThreadsTextField, 1, 5, 3);
        // 第7行: 按钮
        gridBagAddItem(submitBtn, 0, 6, 3);
        gridBagAddItem(saveBtn, 3, 6, 3);
        gridBagAddItem(exitBtn, 6, 6, 3);
        // 第8行: 扫描结果
        gridBagAddItem(labels[3], 0, 7, 10);
        resultTextArea.setLineWrap(true);
        resultTextArea.setEditable(false);
        ctrs.gridheight = 4;
        gridBagAddItem(resultJPanel, 0,8, 10);
        //第9行：进度条
        progressBar.setMaximum(100);
        progressBar.setMinimum(0);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        gridBagAddItem(progressBar,0,13,10);

    }

    private void gridBagAddItem(JComponent component, int gridx, int gridy, int gridwidth) {
        ctrs.gridx = gridx;
        ctrs.gridy = gridy;
        ctrs.gridwidth = gridwidth;
        mainJPanel.add(component, ctrs);
    }
    @Override
    public void run() {
        logger.debug("{}: 主线程开始运行", this.getClass().getSimpleName());
        showMainFrame();
    }

    private void showMainFrame() {
        main.setSize(700, 650);
        main.setLocation(300, 100);
        main.setResizable(false);
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        main.setVisible(true);
    }


    /**
     * 添加动作监听器的线程类
     */
    private class ActionListenerThread extends Thread {
        ActionListenerThread(Runnable target) {
            super(target);
        }

        @Override
        public void run() {
            logger.debug("{}: 添加动作监听器", this.getClass().getSimpleName());

            // 设置热键及快键键
            setMnemonicAndAccelerator();

            // 设置动作监听
            setActionListener();
        }

        /**
         * 设置热键及快捷键
         */
        private void setMnemonicAndAccelerator() {
            // 设置热键
            fileMenu.setMnemonic(KeyEvent.VK_F);
            scanItem.setMnemonic(KeyEvent.VK_R);
            scanItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK));
            saveItem.setMnemonic(KeyEvent.VK_S);
            saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));  // 快捷键
            exitItem.setMnemonic(KeyEvent.VK_Q);
            exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK));
        }

        /**
         * 设置动作监听
         */
        private void setActionListener() {
            // 扫描键(选项)的动作监听
            ScanAction scanAction = new ScanAction();
            scanItem.addActionListener(scanAction);
            submitBtn.addActionListener(scanAction);

            // 保存键(选项)的动作监听
            SaveAction saveAction = new SaveAction();
            saveItem.addActionListener(saveAction);
            saveBtn.addActionListener(saveAction);

            // 退出键(选项)的动作监听
            exitItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    logger.debug("{}: \"退出\"按钮动作监听器", this.getClass().getSimpleName());
                    System.exit(0);
                }
            });
            exitBtn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    logger.debug("{}: \"退出\"按钮动作监听器", this.getClass().getSimpleName());
                    System.exit(0);
                }
            });

            //TCP和UDP的动作监听

            // 扫描方式Radio键的动作监听
            addrScanJRadio1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (addrScanJRadio1.isSelected()) {
                        for (int i = 0; i < ipAddrTextField.length; i++)
                            ipAddrTextField[i].setEnabled(true);

                        domainNameTextField.setEnabled(false);
                    }
                }
            });
            domeScanJRadio1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (domeScanJRadio1.isSelected()) {
                        domainNameTextField.setEnabled(true);

                        for (int i = 0; i < ipAddrTextField.length; i++)
                            ipAddrTextField[i].setEnabled(false);
                    }
                }
            });

            // 帮助选项的动作监听
            aboutItem.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    new AboutDialog();
                }
            });
        }
    }


}
